#include "util/protocol.hpp"
#include <arpa/inet.h> // for htonl, ntohl
#include <cstring>

namespace protocol {

std::string Message::serialize() const {
    std::string buffer;
    // 总长度 = tag长度 + length字段长度 + value实际长度
    buffer.resize(sizeof(tag) + sizeof(length) + value.size());

    int32_t net_tag = htonl(tag);
    int32_t net_length = htonl(length);

    char* ptr = &buffer[0];
    memcpy(ptr, &net_tag, sizeof(net_tag));
    ptr += sizeof(net_tag);
    memcpy(ptr, &net_length, sizeof(net_length));
    ptr += sizeof(net_length);
    memcpy(ptr, value.c_str(), value.size());

    return buffer;
}

std::pair<bool, size_t> Message::deserialize(const char* data, size_t len) {
    // 检查长度是否至少包含 tag 和 length 字段
    if (len < sizeof(tag) + sizeof(length)) {
        return {false, 0};
    }

    const char* ptr = data;
    memcpy(&tag, ptr, sizeof(tag));
    tag = ntohl(tag);
    ptr += sizeof(tag);

    memcpy(&length, ptr, sizeof(length));
    length = ntohl(length);
    ptr += sizeof(length);
    
    // 检查剩余长度是否足以包含 value
    if (len < sizeof(tag) + sizeof(length) + length) {
        return {false, 0};
    }
    
    value.assign(ptr, length);
    
    // 返回成功和总共读取的字节数
    return {true, sizeof(tag) + sizeof(length) + length};
}

std::vector<Message> MessageParser::parse(const char* data, size_t len, size_t& processedBytes) {
    std::vector<Message> messages;
    processedBytes = 0;
    
    // 将新数据追加到内部缓冲区
    _buffer.insert(_buffer.end(), data, data + len);

    const char* current_data = _buffer.data();
    size_t current_len = _buffer.size();
    
    // 循环解析缓冲区中的数据
    while (current_len > 0) {
        Message msg;
        auto [success, bytes_read] = msg.deserialize(current_data, current_len);
        
        if (success) {
            messages.push_back(msg);
            current_data += bytes_read;
            current_len -= bytes_read;
            processedBytes += bytes_read;
        } else {
            // 数据不够一个完整包，跳出循环，等待更多数据
            break;
        }
    }
    
    // 从缓冲区中移除已成功处理的数据
    if (processedBytes > 0) {
        _buffer.erase(_buffer.begin(), _buffer.begin() + processedBytes);
    }
    
    return messages;
}

} // namespace protocol
